package com.hzw.saas.service.sysuser.service;


import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import javax.annotation.Resource;

import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.IService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hzw.saas.api.rbac.IUserRoleService;
import com.hzw.saas.api.rbac.enums.PermSysEnum;
import com.hzw.saas.api.sys.dto.SysUserAccountDto;
import com.hzw.saas.api.sys.dto.SysUserInfoBO;
import com.hzw.saas.api.sys.service.ISysUserService;
import com.hzw.saas.api.user.IStaffService;
import com.hzw.saas.common.config.exception.DefaultSaasException;
import com.hzw.saas.common.util.Json;
import com.hzw.saas.common.util.MapperUtil;
import com.hzw.saas.common.util.SnowFlakeUtil;
import com.hzw.saas.service.sysuser.mapper.SysUserMapper;
import com.hzw.saas.service.sysuser.pojo.model.SysUser;
import cn.hutool.core.collection.CollectionUtil;
import org.springframework.http.HttpStatus;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import lombok.AllArgsConstructor;

/**
 * <p>
 *
 * </p>
 *
 * @author sonam
 * @since 2021/1/27 23:10
 */
@Service
@AllArgsConstructor
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> implements ISysUserService, IService<SysUser> {

    private final PasswordEncoder passwordEncoder;
    private final IUserRoleService userRoleService;

    @Resource
    private IStaffService staffService;

    @Override
    public boolean exists(String userId) {
        int count = this.count(Wrappers.<SysUser>lambdaQuery().eq(SysUser::getUserId, userId));
        return count > 0;
    }

    @Override
    public boolean exists(SysUserAccountDto query) {

        int count = this.count(Wrappers.<SysUser>lambdaQuery()
            .or().eq(StringUtils.isNotBlank(query.getUserName()), SysUser::getUserId, query.getUserName())
            .or().eq(StringUtils.isNotBlank(query.getPhoneNo()), SysUser::getPhoneNo, query.getPhoneNo())
            .or().eq(StringUtils.isNotBlank(query.getEmail()), SysUser::getEmail, query.getEmail()));
        return count > 0;
    }

    @Override
    public SysUserAccountDto get(String userId) {
        SysUser sysUser = this.getById(userId);
        if (sysUser == null) {
            return null;
        }
        return MapperUtil.nf().map(sysUser, SysUserAccountDto.class);
    }

    @Override
    public SysUserAccountDto get(SysUserAccountDto query) {
        List<SysUser> sysUserList = baseMapper.selectList(Wrappers.<SysUser>lambdaQuery()
            .eq(StringUtils.isNotBlank(query.getUserName()), SysUser::getUserName, query.getUserName())
            .eq(StringUtils.isNotBlank(query.getPhoneNo()), SysUser::getPhoneNo, query.getPhoneNo())
            .eq(StringUtils.isNotBlank(query.getEmail()), SysUser::getEmail, query.getEmail()));
        if (CollectionUtils.isEmpty(sysUserList)) {
            return null;
        }
        return MapperUtil.nf().map(sysUserList.get(0), SysUserAccountDto.class);
    }

    @Override
    public List<SysUserInfoBO> listSysUsers(Collection<String> userIds) {
        if (CollectionUtil.isEmpty(userIds)) {
            return new ArrayList<>();
        }
        return super.baseMapper.listSysUserInfoByPids(userIds, null);
    }

    @Override
    public List<SysUserInfoBO> listSysUsersByEmail(Collection<String> email) {
        if (CollectionUtil.isEmpty(email)) {
            return new ArrayList<>();
        }
        return super.baseMapper.listSysUserInfoByPids(null, email);
    }

    @Override
    public SysUserAccountDto add(SysUserAccountDto SysUserAccountDto) {
        SysUser sysUser = MapperUtil.nf().map(SysUserAccountDto, SysUser.class);
        if (exists(SysUserAccountDto)) {
            throw DefaultSaasException.build("用户已存在").status(HttpStatus.BAD_REQUEST);
        }
        try {
            initUserAccount(sysUser);
            log.debug("add sys user: \r\n" + Json.toJsonString(sysUser));
            baseMapper.insert(sysUser);
        } finally {
            if (sysUser.getPassword() != null && sysUser.getPassword().startsWith("*")) {
                sysUser.setPassword("*");
            } else {
                sysUser.setPassword(null);
            }
        }
        SysUserAccountDto = MapperUtil.nf().map(sysUser, SysUserAccountDto.class);
        return SysUserAccountDto;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public SysUserAccountDto add(SysUserAccountDto sysUserAccountDto, List<String> roleIds) {
        SysUserAccountDto sysUser = this.add(sysUserAccountDto);
        userRoleService.updateUserRole(PermSysEnum.ADMIN.getCode(), sysUser.getUserId(), roleIds);
        return sysUser;
    }

    @Override
    public boolean update(SysUserAccountDto SysUserAccountDto) {
        if (StringUtils.isBlank(SysUserAccountDto.getUserId())) {
            throw DefaultSaasException.build("用户id为空").status(HttpStatus.BAD_REQUEST);
        }
        SysUser sysUser = MapperUtil.nf().map(SysUserAccountDto, SysUser.class);
        return this.updateById(sysUser);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean update(SysUserAccountDto SysUserAccountDto, List<String> roleIds) {
        boolean update = this.update(SysUserAccountDto);
        if (update) {
            userRoleService.updateUserRole(PermSysEnum.ADMIN.getCode(), SysUserAccountDto.getUserId(), roleIds);
        }
        return update;
    }

    @Override
    public boolean resetPassword(String userId, String password) {
        if (StringUtils.isBlank(userId)) {
            return false;
        }
        SysUser sysUser = new SysUser();
        sysUser.setUserId(userId).setPassword(passwordEncoder.encode(password));
        int updateNum = this.baseMapper.updateById(sysUser);
        return updateNum > 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean delete(String userId) {
        boolean remove = super.removeById(userId);
        if (remove) {
            userRoleService.deleteUser(PermSysEnum.ADMIN.getCode(), userId);
        }
        return remove;
    }

    private void initUserAccount(SysUser sysUser) {
        Date now = new Date();
        sysUser.setUserId(SnowFlakeUtil.nextIdStr());
        sysUser.setRegisteredDate(now);
        sysUser.setPassword(passwordEncoder.encode(sysUser.getPassword()));

        // 默认启用用户
        if (sysUser.getStatus() == null) {
            sysUser.setStatus(1);
        }
    }
}
